"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "openssl 0.9.12 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl 0.9.13 (registry+https://github.com/rust-lang/crates.io-index)",
"psapi-sys 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
"semver 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_ignored 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"shell-escape 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "tar 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tar 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)",
"tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
"term 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
"toml 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "url 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "url 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "backtrace-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "backtrace-sys 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
"cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
[[package]]
name = "backtrace-sys"
-version = "0.1.10"
+version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"gcc 0.3.50 (registry+https://github.com/rust-lang/crates.io-index)",
[[package]]
name = "bitflags"
-version = "0.8.2"
+version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
"rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "tar 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tar 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)",
"tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
"term 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "url 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "url 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
"serde 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "url 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "url 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
"curl-sys 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
"openssl-probe 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "openssl-sys 0.9.12 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl-sys 0.9.13 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
"gcc 0.3.50 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
"libz-sys 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)",
- "openssl-sys 0.9.12 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl-sys 0.9.13 (registry+https://github.com/rust-lang/crates.io-index)",
"pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
"libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
"libgit2-sys 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
"openssl-probe 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "openssl-sys 0.9.12 (registry+https://github.com/rust-lang/crates.io-index)",
- "url 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl-sys 0.9.13 (registry+https://github.com/rust-lang/crates.io-index)",
+ "url 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
"curl 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"git2 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "url 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "url 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "unicode-bidi 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unicode-bidi 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-normalization 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
"libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
"libssh2-sys 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
"libz-sys 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)",
- "openssl-sys 0.9.12 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl-sys 0.9.13 (registry+https://github.com/rust-lang/crates.io-index)",
"pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
]
"cmake 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
"libz-sys 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)",
- "openssl-sys 0.9.12 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl-sys 0.9.13 (registry+https://github.com/rust-lang/crates.io-index)",
"pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "openssl"
-version = "0.9.12"
+version = "0.9.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "bitflags 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
"foreign-types 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
- "openssl-sys 0.9.12 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl-sys 0.9.13 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
[[package]]
name = "openssl-sys"
-version = "0.9.12"
+version = "0.9.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"gcc 0.3.50 (registry+https://github.com/rust-lang/crates.io-index)",
[[package]]
name = "tar"
-version = "0.4.12"
+version = "0.4.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
[[package]]
name = "unicode-bidi"
-version = "0.3.2"
+version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
[[package]]
name = "url"
-version = "1.4.0"
+version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"idna 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"checksum aho-corasick 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ca972c2ea5f742bfce5687b9aef75506a764f61d37f8f649047846a9686ddb66"
"checksum aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "500909c4f87a9e52355b26626d890833e9e1d53ac566db76c36faa984b889699"
"checksum backtrace 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "72f9b4182546f4b04ebc4ab7f84948953a118bd6021a1b6a6c909e3e94f6be76"
-"checksum backtrace-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "d192fd129132fbc97497c1f2ec2c2c5174e376b95f535199ef4fe0a293d33842"
+"checksum backtrace-sys 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "3a0d842ea781ce92be2bf78a9b38883948542749640b8378b3b2f03d1fd9f1ff"
"checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d"
-"checksum bitflags 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1370e9fc2a6ae53aea8b7a5110edbd08836ed87c88736dfabccade1c2b44bff4"
+"checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5"
"checksum bufstream 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f2f382711e76b9de6c744cc00d0497baba02fb00a787f088c879f01d09468e32"
"checksum cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de1e760d7b6535af4241fca8bd8adf68e2e7edacc6b29f5d399050c5e48cf88c"
"checksum cmake 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)" = "b8ebbb35d3dc9cd09497168f33de1acb79b265d350ab0ac34133b98f8509af1f"
"checksum num-rational 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)" = "c2dc5ea04020a8f18318ae485c751f8cfa1c0e69dcf465c29ddaaa64a313cc44"
"checksum num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "e1cbfa3781f3fe73dc05321bed52a06d2d491eaa764c52335cf4399f046ece99"
"checksum num_cpus 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f6e850c7f35c3de263e6094e819f6b4b9c09190ff4438fc6dec1aef1568547bc"
-"checksum openssl 0.9.12 (registry+https://github.com/rust-lang/crates.io-index)" = "bb5d1663b73d10c6a3eda53e2e9d0346f822394e7b858d7257718f65f61dfbe2"
+"checksum openssl 0.9.13 (registry+https://github.com/rust-lang/crates.io-index)" = "b34cd77cf91301fff3123fbd46b065c3b728b17a392835de34c397315dce5586"
"checksum openssl-probe 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d98df0270d404ccd3c050a41d579c52d1db15375168bb3471e04ec0f5f378daf"
-"checksum openssl-sys 0.9.12 (registry+https://github.com/rust-lang/crates.io-index)" = "3a5886d87d3e2a0d890bf62dc8944f5e3769a405f7e1e9ef6e517e47fd7a0897"
+"checksum openssl-sys 0.9.13 (registry+https://github.com/rust-lang/crates.io-index)" = "e035022a50faa380bd7ccdbd184d946ce539ebdb0a358780de92a995882af97a"
"checksum pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3a8b4c6b8165cd1a1cd4b9b120978131389f64bdaf456435caa41e630edba903"
"checksum psapi-sys 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "abcd5d1a07d360e29727f757a9decb3ce8bc6e0efa8969cfaad669a8317a2478"
"checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a"
"checksum strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d15c810519a91cf877e7e36e63fe068815c678181439f2f29e2562147c3694"
"checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad"
"checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6"
-"checksum tar 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "ab0ef9ead2fe0aa9e18475a96a207bfd5143f4124779ef7429503a8665416ce8"
+"checksum tar 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)" = "281285b717926caa919ad905ef89c63d75805c7d89437fb873100925a53f2b1b"
"checksum tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "87974a6f5c1dfb344d733055601650059a3363de2a6104819293baff662132d6"
"checksum term 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d168af3930b369cfe245132550579d47dfd873d69470755a19c2c6568dbbd989"
"checksum thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9539db560102d1cef46b8b78ce737ff0bb64e7e18d35b2a5688f7d097d0ff03"
"checksum thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8576dbbfcaef9641452d5cf0df9b0e7eeab7694956dd33bb61515fb8f18cfdd5"
"checksum thread_local 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c85048c6260d17cf486ceae3282d9fb6b90be220bf5b28c400f5485ffc29f0c7"
"checksum toml 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4cc5dbfb20a481e64b99eb7ae280859ec76730c7191570ba5edaa962394edb0a"
-"checksum unicode-bidi 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "916219eb752dd865717c9b21064401c6ee843dc91ed659c144591e0c87c56d59"
+"checksum unicode-bidi 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a6a2c4e3710edd365cd7e78383153ed739fa31af19f9172f72d3575060f5a43a"
"checksum unicode-normalization 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "e28fa37426fceeb5cf8f41ee273faa7c82c47dc8fba5853402841e665fcd86ff"
"checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc"
"checksum unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1f2ae5ddb18e1c92664717616dd9549dde73f539f01bd7b77c2edb2446bdff91"
-"checksum url 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f5ba8a749fb4479b043733416c244fa9d1d3af3d7c23804944651c8a448cb87e"
+"checksum url 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3e2ba3456fbe5c0098cb877cf08b92b76c3e18e0be9e47c35b487220d377d24e"
"checksum user32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ef4711d107b21b410a3a974b1204d9accc8b10dad75d8324b5d755de1617d47"
"checksum utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a1ca13c08c41c9c3e04224ed9ff80461d97e121589ff27c753a16cb10830ae0f"
"checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122"
use std::collections::{HashSet, HashMap, BinaryHeap, BTreeMap};
use std::iter::FromIterator;
use std::fmt;
+use std::mem;
use std::ops::Range;
use std::rc::Rc;
///
/// Each instance of `Resolve` also understands the full set of features used
/// for each package.
-#[derive(PartialEq, Eq, Clone)]
+#[derive(Clone)]
pub struct Resolve {
graph: Graph<PackageId>,
replacements: HashMap<PackageId, PackageId>,
// Information about the dependencies for a crate, a tuple of:
//
// (dependency info, candidates, features activated)
-type DepInfo = (Dependency, Vec<Candidate>, Vec<String>);
+type DepInfo = (Dependency, Rc<Vec<Candidate>>, Rc<Vec<String>>);
#[derive(Clone)]
struct Candidate {
- summary: Rc<Summary>,
- replace: Option<Rc<Summary>>,
+ summary: Summary,
+ replace: Option<Summary>,
}
impl Resolve {
}
}
+enum RcList<T> {
+ Data(Rc<(T, RcList<T>)>),
+ Empty,
+}
+
+impl<T> RcList<T> {
+ fn new() -> RcList<T> {
+ RcList::Empty
+ }
+
+ fn push(&mut self, data: T) {
+ let node = Rc::new((data, mem::replace(self, RcList::Empty)));
+ *self = RcList::Data(node);
+ }
+}
+
+// Not derived to avoid `T: Clone`
+impl<T> Clone for RcList<T> {
+ fn clone(&self) -> RcList<T> {
+ match *self {
+ RcList::Data(ref d) => RcList::Data(d.clone()),
+ RcList::Empty => RcList::Empty,
+ }
+ }
+}
+
+enum GraphNode {
+ Add(PackageId),
+ Link(PackageId, PackageId),
+}
+
#[derive(Clone)]
struct Context<'a> {
- activations: HashMap<(String, SourceId), Vec<Rc<Summary>>>,
- resolve_graph: Graph<PackageId>,
+ activations: HashMap<String, HashMap<SourceId, Vec<Summary>>>,
+ resolve_graph: RcList<GraphNode>,
resolve_features: HashMap<PackageId, HashSet<String>>,
- resolve_replacements: HashMap<PackageId, PackageId>,
+ resolve_replacements: RcList<(PackageId, PackageId)>,
replacements: &'a [(PackageIdSpec, Dependency)],
}
replacements: &[(PackageIdSpec, Dependency)],
registry: &mut Registry) -> CargoResult<Resolve> {
let cx = Context {
- resolve_graph: Graph::new(),
+ resolve_graph: RcList::new(),
resolve_features: HashMap::new(),
- resolve_replacements: HashMap::new(),
+ resolve_replacements: RcList::new(),
activations: HashMap::new(),
replacements: replacements,
};
let cx = activate_deps_loop(cx, registry, summaries)?;
let mut resolve = Resolve {
- graph: cx.resolve_graph,
+ graph: cx.graph(),
empty_features: HashSet::new(),
- features: cx.resolve_features,
checksums: HashMap::new(),
metadata: BTreeMap::new(),
- replacements: cx.resolve_replacements,
+ replacements: cx.resolve_replacements(),
+ features: cx.resolve_features.iter().map(|(k, v)| {
+ (k.clone(), v.clone())
+ }).collect(),
};
- for summary in cx.activations.values().flat_map(|v| v.iter()) {
+ for summary in cx.activations.values()
+ .flat_map(|v| v.values())
+ .flat_map(|v| v.iter()) {
let cksum = summary.checksum().map(|s| s.to_string());
resolve.checksums.insert(summary.package_id().clone(), cksum);
}
/// iterate through next.
fn activate(cx: &mut Context,
registry: &mut Registry,
- parent: Option<&Rc<Summary>>,
+ parent: Option<&Summary>,
candidate: Candidate,
method: &Method)
-> CargoResult<Option<DepsFrame>> {
if let Some(parent) = parent {
- cx.resolve_graph.link(parent.package_id().clone(),
- candidate.summary.package_id().clone());
+ cx.resolve_graph.push(GraphNode::Link(parent.package_id().clone(),
+ candidate.summary.package_id().clone()));
}
let activated = cx.flag_activated(&candidate.summary, method);
let candidate = match candidate.replace {
Some(replace) => {
- cx.resolve_replacements.insert(candidate.summary.package_id().clone(),
- replace.package_id().clone());
+ cx.resolve_replacements.push((candidate.summary.package_id().clone(),
+ replace.package_id().clone()));
if cx.flag_activated(&replace, method) && activated {
return Ok(None);
}
Ok(Some(DepsFrame {
parent: candidate,
- remaining_siblings: RcVecIter::new(deps),
+ remaining_siblings: RcVecIter::new(Rc::new(deps)),
}))
}
-#[derive(Clone)]
struct RcVecIter<T> {
vec: Rc<Vec<T>>,
rest: Range<usize>,
}
impl<T> RcVecIter<T> {
- fn new(vec: Vec<T>) -> RcVecIter<T> {
+ fn new(vec: Rc<Vec<T>>) -> RcVecIter<T> {
RcVecIter {
rest: 0..vec.len(),
- vec: Rc::new(vec),
+ vec: vec,
}
}
fn cur_index(&self) -> usize {
self.rest.start - 1
}
+}
- fn as_slice(&self) -> &[T] {
- &self.vec[self.rest.start..self.rest.end]
+// Not derived to avoid `T: Clone`
+impl<T> Clone for RcVecIter<T> {
+ fn clone(&self) -> RcVecIter<T> {
+ RcVecIter {
+ vec: self.vec.clone(),
+ rest: self.rest.clone(),
+ }
}
}
impl<T> Iterator for RcVecIter<T> where T: Clone {
type Item = (usize, T);
+
fn next(&mut self) -> Option<(usize, T)> {
self.rest.next().and_then(|i| {
self.vec.get(i).map(|val| (i, val.clone()))
})
}
+
fn size_hint(&self) -> (usize, Option<usize>) {
self.rest.size_hint()
}
#[derive(Clone)]
struct DepsFrame {
- parent: Rc<Summary>,
+ parent: Summary,
remaining_siblings: RcVecIter<DepInfo>,
}
/// number of candidates at the front, so we just return the number of
/// candidates in that entry.
fn min_candidates(&self) -> usize {
- self.remaining_siblings.as_slice().get(0).map(|&(_, ref candidates, _)| {
+ self.remaining_siblings.clone().next().map(|(_, (_, candidates, _))| {
candidates.len()
}).unwrap_or(0)
}
struct BacktrackFrame<'a> {
context_backup: Context<'a>,
deps_backup: BinaryHeap<DepsFrame>,
- remaining_candidates: RcVecIter<Candidate>,
- parent: Rc<Summary>,
+ remaining_candidates: RemainingCandidates,
+ parent: Summary,
dep: Dependency,
- features: Vec<String>,
+ features: Rc<Vec<String>>,
+}
+
+#[derive(Clone)]
+struct RemainingCandidates {
+ remaining: RcVecIter<Candidate>,
+}
+
+impl RemainingCandidates {
+ fn next(&mut self, prev_active: &[Summary]) -> Option<Candidate> {
+ // Filter the set of candidates based on the previously activated
+ // versions for this dependency. We can actually use a version if it
+ // precisely matches an activated version or if it is otherwise
+ // incompatible with all other activated versions. Note that we
+ // define "compatible" here in terms of the semver sense where if
+ // the left-most nonzero digit is the same they're considered
+ // compatible.
+ self.remaining.by_ref().map(|p| p.1).filter(|b| {
+ prev_active.iter().any(|a| *a == b.summary) ||
+ prev_active.iter().all(|a| {
+ !compatible(a.version(), b.summary.version())
+ })
+ }).next()
+ }
}
/// Recursively activates the dependencies for `top`, in depth-first order,
let mut remaining_deps = BinaryHeap::new();
for &(ref summary, ref method) in summaries {
debug!("initial activation: {}", summary.package_id());
- let summary = Rc::new(summary.clone());
- let candidate = Candidate { summary: summary, replace: None };
+ let candidate = Candidate { summary: summary.clone(), replace: None };
remaining_deps.extend(activate(&mut cx, registry, None, candidate,
method)?);
}
while let Some(mut deps_frame) = remaining_deps.pop() {
let frame = match deps_frame.remaining_siblings.next() {
Some(sibling) => {
- let parent = deps_frame.parent.clone();
+ let parent = Summary::clone(&deps_frame.parent);
remaining_deps.push(deps_frame);
(parent, sibling)
}
let (mut parent, (mut cur, (mut dep, candidates, mut features))) = frame;
assert!(!remaining_deps.is_empty());
- let my_candidates = {
+ let (next, has_another, remaining_candidates) = {
let prev_active = cx.prev_active(&dep);
trace!("{}[{}]>{} {} candidates", parent.name(), cur, dep.name(),
candidates.len());
trace!("{}[{}]>{} {} prev activations", parent.name(), cur,
dep.name(), prev_active.len());
-
- // Filter the set of candidates based on the previously activated
- // versions for this dependency. We can actually use a version if it
- // precisely matches an activated version or if it is otherwise
- // incompatible with all other activated versions. Note that we
- // define "compatible" here in terms of the semver sense where if
- // the left-most nonzero digit is the same they're considered
- // compatible.
- candidates.iter().filter(|&b| {
- prev_active.iter().any(|a| *a == b.summary) ||
- prev_active.iter().all(|a| {
- !compatible(a.version(), b.summary.version())
- })
- }).cloned().collect()
+ let mut candidates = RemainingCandidates {
+ remaining: RcVecIter::new(Rc::clone(&candidates)),
+ };
+ (candidates.next(prev_active),
+ candidates.clone().next(prev_active).is_some(),
+ candidates)
};
// Alright, for each candidate that's gotten this far, it meets the
// This means that we're going to attempt to activate each candidate in
// turn. We could possibly fail to activate each candidate, so we try
// each one in turn.
- let mut remaining_candidates = RcVecIter::new(my_candidates);
- let candidate = match remaining_candidates.next() {
- Some((_, candidate)) => {
+ let candidate = match next {
+ Some(candidate) => {
// We have a candidate. Add an entry to the `backtrack_stack` so
// we can try the next one if this one fails.
- backtrack_stack.push(BacktrackFrame {
- context_backup: cx.clone(),
- deps_backup: remaining_deps.clone(),
- remaining_candidates: remaining_candidates,
- parent: parent.clone(),
- dep: dep.clone(),
- features: features.clone(),
- });
+ if has_another {
+ backtrack_stack.push(BacktrackFrame {
+ context_backup: Context::clone(&cx),
+ deps_backup: <BinaryHeap<DepsFrame>>::clone(&remaining_deps),
+ remaining_candidates: remaining_candidates,
+ parent: Summary::clone(&parent),
+ dep: Dependency::clone(&dep),
+ features: Rc::clone(&features),
+ });
+ }
candidate
}
None => {
fn find_candidate<'a>(backtrack_stack: &mut Vec<BacktrackFrame<'a>>,
cx: &mut Context<'a>,
remaining_deps: &mut BinaryHeap<DepsFrame>,
- parent: &mut Rc<Summary>,
+ parent: &mut Summary,
cur: &mut usize,
dep: &mut Dependency,
- features: &mut Vec<String>) -> Option<Candidate> {
+ features: &mut Rc<Vec<String>>) -> Option<Candidate> {
while let Some(mut frame) = backtrack_stack.pop() {
- if let Some((_, candidate)) = frame.remaining_candidates.next() {
- *cx = frame.context_backup.clone();
- *remaining_deps = frame.deps_backup.clone();
- *parent = frame.parent.clone();
+ let (next, has_another) = {
+ let prev_active = frame.context_backup.prev_active(&frame.dep);
+ (frame.remaining_candidates.next(prev_active),
+ frame.remaining_candidates.clone().next(prev_active).is_some())
+ };
+ if let Some(candidate) = next {
+ if has_another {
+ *cx = frame.context_backup.clone();
+ *remaining_deps = frame.deps_backup.clone();
+ *parent = frame.parent.clone();
+ *dep = frame.dep.clone();
+ *features = frame.features.clone();
+ backtrack_stack.push(frame);
+ } else {
+ *cx = frame.context_backup;
+ *remaining_deps = frame.deps_backup;
+ *parent = frame.parent;
+ *dep = frame.dep;
+ *features = frame.features;
+ }
*cur = remaining_deps.peek().unwrap().remaining_siblings.cur_index();
- *dep = frame.dep.clone();
- *features = frame.features.clone();
- backtrack_stack.push(frame);
return Some(candidate)
}
}
registry: &mut Registry,
parent: &Summary,
dep: &Dependency,
- prev_active: &[Rc<Summary>],
+ prev_active: &[Summary],
candidates: &[Candidate]) -> CargoError {
if candidates.len() > 0 {
let mut msg = format!("failed to select a version for `{}` \
previously selected versions of `{}`",
dep.name(), parent.name(),
dep.name());
+ let graph = cx.graph();
'outer: for v in prev_active.iter() {
- for node in cx.resolve_graph.iter() {
- let edges = match cx.resolve_graph.edges(node) {
+ for node in graph.iter() {
+ let edges = match graph.edges(node) {
Some(edges) => edges,
None => continue,
};
// allows any version so we can give some nicer error reporting
// which indicates a few versions that were actually found.
let all_req = semver::VersionReq::parse("*").unwrap();
- let new_dep = dep.clone_inner().set_version_req(all_req).into_dependency();
+ let mut new_dep = dep.clone();
+ new_dep.set_version_req(all_req);
let mut candidates = match registry.query(&new_dep) {
Ok(candidates) => candidates,
Err(e) => return e,
// The all used features set is the set of features which this local package had
// enabled, which is later used when compiling to instruct the code what
// features were enabled.
-fn build_features(s: &Summary, method: &Method)
- -> CargoResult<(HashMap<String, Vec<String>>, HashSet<String>)> {
+fn build_features<'a>(s: &'a Summary, method: &'a Method)
+ -> CargoResult<(HashMap<&'a str, Vec<String>>, HashSet<&'a str>)> {
let mut deps = HashMap::new();
let mut used = HashSet::new();
let mut visited = HashSet::new();
}
return Ok((deps, used));
- fn add_feature(s: &Summary, feat: &str,
- deps: &mut HashMap<String, Vec<String>>,
- used: &mut HashSet<String>,
- visited: &mut HashSet<String>) -> CargoResult<()> {
+ fn add_feature<'a>(s: &'a Summary,
+ feat: &'a str,
+ deps: &mut HashMap<&'a str, Vec<String>>,
+ used: &mut HashSet<&'a str>,
+ visited: &mut HashSet<&'a str>) -> CargoResult<()> {
if feat.is_empty() { return Ok(()) }
// If this feature is of the form `foo/bar`, then we just lookup package
match parts.next() {
Some(feat) => {
let package = feat_or_package;
- used.insert(package.to_string());
- deps.entry(package.to_string())
+ used.insert(package);
+ deps.entry(package)
.or_insert(Vec::new())
.push(feat.to_string());
}
None => {
let feat = feat_or_package;
- if !visited.insert(feat.to_string()) {
+ if !visited.insert(feat) {
bail!("Cyclic feature dependency: feature `{}` depends \
on itself", feat)
}
- used.insert(feat.to_string());
+ used.insert(feat);
match s.features().get(feat) {
Some(recursive) => {
for f in recursive {
}
}
None => {
- deps.entry(feat.to_string()).or_insert(Vec::new());
+ deps.entry(feat).or_insert(Vec::new());
}
}
- visited.remove(&feat.to_string());
+ visited.remove(feat);
}
}
Ok(())
//
// Returns if this summary with the given method is already activated.
fn flag_activated(&mut self,
- summary: &Rc<Summary>,
+ summary: &Summary,
method: &Method) -> bool {
let id = summary.package_id();
- let key = (id.name().to_string(), id.source_id().clone());
- let prev = self.activations.entry(key).or_insert(Vec::new());
+ let prev = self.activations
+ .entry(id.name().to_string())
+ .or_insert_with(HashMap::new)
+ .entry(id.source_id().clone())
+ .or_insert(Vec::new());
if !prev.iter().any(|c| c == summary) {
- self.resolve_graph.add(id.clone(), &[]);
+ self.resolve_graph.push(GraphNode::Add(id.clone()));
prev.push(summary.clone());
return false
}
candidates.sort_by(|a, b| {
b.summary.version().cmp(a.summary.version())
});
- Ok((dep, candidates, features))
+ Ok((dep, Rc::new(candidates), Rc::new(features)))
}).collect::<CargoResult<Vec<DepInfo>>>()?;
// Attempt to resolve dependencies with fewer candidates before trying
registry: &mut Registry,
dep: &Dependency) -> CargoResult<Vec<Candidate>> {
let summaries = registry.query(dep)?;
- summaries.into_iter().map(Rc::new).map(|summary| {
+ summaries.into_iter().map(|summary| {
// get around lack of non-lexical lifetimes
let summary2 = summary.clone();
debug!("Preventing\n{:?}\nfrom replacing\n{:?}", summary, s);
None
} else {
- Some(Rc::new(s))
+ Some(s)
};
let matched_spec = spec.clone();
}).collect()
}
- fn prev_active(&self, dep: &Dependency) -> &[Rc<Summary>] {
- let key = (dep.name().to_string(), dep.source_id().clone());
- self.activations.get(&key).map(|v| &v[..]).unwrap_or(&[])
+ fn prev_active(&self, dep: &Dependency) -> &[Summary] {
+ self.activations.get(dep.name())
+ .and_then(|v| v.get(dep.source_id()))
+ .map(|v| &v[..])
+ .unwrap_or(&[])
}
- fn resolve_features(&mut self, candidate: &Summary, method: &Method)
- -> CargoResult<Vec<(Dependency, Vec<String>)>> {
+ fn resolve_features<'b>(&mut self,
+ candidate: &'b Summary,
+ method: &'b Method)
+ -> CargoResult<Vec<(Dependency, Vec<String>)>> {
let dev_deps = match *method {
Method::Everything => true,
Method::Required { dev_deps, .. } => dev_deps,
let deps = deps.iter().filter(|d| d.is_transitive() || dev_deps);
let (mut feature_deps, used_features) = build_features(candidate,
- method)?;
+ method)?;
let mut ret = Vec::new();
// Next, sanitize all requested features by whitelisting all the
continue
}
let mut base = feature_deps.remove(dep.name()).unwrap_or(vec![]);
- base.extend(dep.features().iter().map(|x| x.clone()));
+ base.extend(dep.features().iter().cloned());
for feature in base.iter() {
if feature.contains("/") {
bail!("feature names may not contain slashes: `{}`", feature);
// Record what list of features is active for this package.
if !used_features.is_empty() {
let pkgid = candidate.package_id();
- self.resolve_features.entry(pkgid.clone())
- .or_insert(HashSet::new())
- .extend(used_features);
+
+ let mut set = self.resolve_features.entry(pkgid.clone())
+ .or_insert_with(HashSet::new);
+ for feature in used_features {
+ if !set.contains(feature) {
+ set.insert(feature.to_string());
+ }
+ }
}
Ok(ret)
}
+
+ fn resolve_replacements(&self) -> HashMap<PackageId, PackageId> {
+ let mut replacements = HashMap::new();
+ let mut cur = &self.resolve_replacements;
+ while let RcList::Data(ref d) = *cur {
+ let (k, v) = d.0.clone();
+ replacements.insert(k, v);
+ cur = &d.1;
+ }
+ return replacements
+ }
+
+ fn graph(&self) -> Graph<PackageId> {
+ let mut graph = Graph::new();
+ let mut cur = &self.resolve_graph;
+ while let RcList::Data(ref d) = *cur {
+ match d.0 {
+ GraphNode::Add(ref p) => graph.add(p.clone(), &[]),
+ GraphNode::Link(ref a, ref b) => graph.link(a.clone(), b.clone()),
+ }
+ cur = &d.1;
+ }
+ return graph
+ }
}
fn check_cycles(resolve: &Resolve,
- activations: &HashMap<(String, SourceId), Vec<Rc<Summary>>>)
+ activations: &HashMap<String, HashMap<SourceId, Vec<Summary>>>)
-> CargoResult<()> {
let summaries: HashMap<&PackageId, &Summary> = activations.values()
+ .flat_map(|v| v.values())
.flat_map(|v| v)
- .map(|s| (s.package_id(), &**s))
+ .map(|s| (s.package_id(), s))
.collect();
// Sort packages to produce user friendly deterministic errors.